#include "FleetAttackPlanet.hh"
#include "Done.hh"
#include "XmlServerThread.hh"
#include "../World/Fleet.hh"
#include "../World/Fleet/AttackPlanet.hh"
#include "../Exception.hh"

using namespace Network;
using namespace World;

struct FapFleetInvalid {
    void operator () () {
        throw NonFatalProtocolError("game.fleet_attack_planet.fleet invalid");
    }
};

struct FapStarInvalid {
    void operator () () {
        throw NonFatalProtocolError("game.fleet_attack_planet.star invalid");
    }
};

struct FapPlanetInvalid {
    void operator () () {
        throw NonFatalProtocolError("game.fleet_attack_planet.planet invalid");
    }
};

spFleetAttackPlanet FleetAttackPlanet::construct(QDomElement const& message) {
    QDomElement const fleetElem = message.firstChildElement("fleet");
    QDomElement const starElem = message.firstChildElement("star");
    QDomElement const planetElem = message.firstChildElement("planet");
    return spFleetAttackPlanet(new FleetAttackPlanet(
      ::parse_num< u8, FapFleetInvalid  >(fleetElem),
      ::parse_num< u8, FapStarInvalid   >(starElem),
      ::parse_num< u1, FapPlanetInvalid >(planetElem)
    ));
}

FleetAttackPlanet::FleetAttackPlanet(u8 fleetId, u8 starId, u1 planetId):
    fleetId(fleetId),
    starId(starId),
    planetId(planetId) {}

void FleetAttackPlanet::process_on_server(XmlServerThread& thread) {
    if (thread.get_state() != GAME)
        throw NonFatalProtocolError("game.fleet_attack_planet unexpected");

    try {
        spPlayer player = thread.get_player();
        spFleet fleet = player->get_fleet(fleetId);
        spPlanet planet =
          player->get_galaxy()->get_star(starId)->get_planet(planetId);
        fleet->set_command(new Fleet::AttackPlanet(planet));
        Done done(true, "game.fleet_attack_planet ok");
        done.send_to(*thread.get_socket());
    } catch (FleetNotFound& ex) {
        Done done(false, ex.what());
        done.send_to(*thread.get_socket());
    }
}

QDomDocument FleetAttackPlanet::to_xml() const {
    QDomDocument doc;
    QDomElement gameElem = doc.createElement("game");
    QDomElement fleetAttackPlanetElem =
      doc.createElement("fleet_attack_planet");
    doc.appendChild(gameElem);
    gameElem.appendChild(fleetAttackPlanetElem);
    ::to_xml(fleetAttackPlanetElem, "fleet",  fleetId);
    ::to_xml(fleetAttackPlanetElem, "star",   starId);
    ::to_xml(fleetAttackPlanetElem, "planet", planetId);
    return doc;
}
